package org.mtmi.ui.controls;

import org.mtmi.tuio.listeners.DragListener;
import org.mtmi.tuio.listeners.TUIODragEvent;
import org.mtmi.tuio.listeners.TUIOTapEvent;
import org.mtmi.ui.scenes.Scene;

/**
 * A control displaying a value, and two are '-', '+'.<p>
 * This layer is independent from face of control.
 */
public abstract class AbstractSpinner extends AbstractRangeValueControl implements DragListener 
{

	public AbstractSpinner( Scene scene, int valCurrent, int valMin, int valMax, int flags ) {
		super(scene, valCurrent, valMin, valMax, flags);
	}

	/** @return true if point is inside the area used to decrement value */
	protected abstract boolean isPreviousValueAreaContains( int x, int y );
	/** @return true if point is inside the area used to increment value */
	protected abstract boolean isNextValueAreaContains( int x, int y );
	/** @return true if point is inside the area used to display value */
	protected abstract boolean isValueAreaContains( int x, int y );
	
	/** Change value to previous or next one */
	protected void changeValue( boolean next ) {
		int value = getValue();
		if( next ) {
			if( value < getMaxValue() ) {
				setValue( value+1 );
			}
		} else {
			if( value  > getMinValue() ) {
				setValue( value-1 );
			}
		}
	}
	
	/** Change value to previous one */
	protected void previousValue() {
		int value = getValue();
		if( value > getMinValue() ) {
			setValue( value-1 );
		}
	}
	
	private boolean dragging;
	private int lx,ly;
	
	@Override
	public void tapDown( TUIOTapEvent e )
	{
		if( isPreviousValueAreaContains( e.ex, e.ey ) ) {
			changeValue( false );
		}
		else if( isNextValueAreaContains( e.ex, e.ey ) ) {
			changeValue( true );
		}
		else if( isValueAreaContains( e.ex, e.ey ) ) {
			dragging = true;
			lx = e.ex;
			ly = e.ey;
		}
	}

	@Override
	public void tapUp(TUIOTapEvent event) {
		dragging=false;
	}
	
	@Override
	public void drag(TUIODragEvent event) {
		if( dragging ) {
			int dx = event.ex-lx;
			int dy = -(event.ey-ly); //y are reversed
			//to right or top: increment, else decrement
			int d = ( Math.abs(dx)>Math.abs(dy))? dx :dy;
			int dv = d/10;
			if( dv != 0 ) {
				setValue( getValue()+dv );
				lx=event.ex;
				ly=event.ey;
			}
		}
	}


}
